package juc.thread;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;

/*
*交替输出
* */
public class Test7 {
    static Thread t1;
    static Thread t2;
    static Thread t3;
    public static void main(String[] args) throws InterruptedException {
       /* WaitNotify waitNotify = new WaitNotify((short) 1, (short)100);
        new Thread(()->{
            waitNotify.print("a",(short) 1,(short) 2);
        }).start();
        new Thread(()->{
            waitNotify.print("b",(short) 2,(short) 3);
        }).start();
        new Thread(()->{
            waitNotify.print("c",(short) 3,(short) 1);
        }).start();*/



       /* AwaitSingle awaitSingle = new AwaitSingle(100);
        Condition a = awaitSingle.newCondition();
        Condition b = awaitSingle.newCondition();
        Condition c = awaitSingle.newCondition();
        new Thread(()->{
            awaitSingle.print("a",a,b);
        }).start();
        new Thread(()->{
            awaitSingle.print("b",b,c);
        }).start();
        new Thread(()->{
            awaitSingle.print("c",c,a);
        }).start();
        Thread.sleep(1000);
        awaitSingle.lock();
        try {
            a.signalAll();
        } finally {
            awaitSingle.unlock();
        }*/
        ParkUnpark parkUnpark = new ParkUnpark(100);
        t1 = new Thread(() -> {
            parkUnpark.print("a",t2);
        },"t1");
        t2 = new Thread(() -> {
            parkUnpark.print("b",t3);
        },"t2");
        t3 = new Thread(() -> {
            parkUnpark.print("c",t1);
        },"t3");
        t1.start();
        t2.start();
        t3.start();
        LockSupport.unpark(t1);
    }
}
/*
*           a   b   c
* flag      1   2   3
* nextflag  2   3   1
* */
class WaitNotify{
      private short flag;//标志那个字母可以结束等待
      private int loopNum;//循环次数

    public WaitNotify(short initflag, int loopNum) {
        this.flag = initflag;
        this.loopNum = loopNum;
    }
    public void print(String str, short flag, short nextflag){
          for (int i=0;i<loopNum;i++) {
              synchronized (this){
                  while (flag!=this.flag){
                      try {
                          this.wait();
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                  }
                  System.out.print(str);
                  this.flag=nextflag;
                  this.notifyAll();
              }
          }
      }
}
class AwaitSingle extends ReentrantLock {
    private int loopNum;//循环次数
    public AwaitSingle(int loopNum){
        this.loopNum=loopNum;
    }
    public void print(String str, Condition now,Condition next){
        for (int i=0;i<loopNum;i++) {
            try {
                Thread.sleep(100);//在这会有隐患 如果再上锁之前出现STW（模拟stw） 可能会导致三个线程一直等待
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            lock();
            try {
                now.await();
                System.out.print(str);
                next.signalAll();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                unlock();
            }
        }
    }
}
class ParkUnpark{
      private int loopNum;

    public ParkUnpark(int loopNum) {
        this.loopNum = loopNum;
    }
    public void print(String str,Thread next){
        for (int i=0;i<loopNum;i++) {
            LockSupport.park();
            System.out.print(str);
            LockSupport.unpark(next);
        }
    }
}
